package com.neulogistics.contrib.procuredcenter.api.application.command.handler;

import com.blackto.lib.mediat.unicast.IRequestHandler;
import com.neulogistics.contrib.procuredcenter.api.application.command.CreateGoodsCommand;
import com.neulogistics.contrib.procuredcenter.api.application.integrationevent.IProcuredCenterIntegrationEventService;
import com.neulogistics.contrib.procuredcenter.api.application.integrationevent.publish.GoodsCreatedIntegrationEvent;
import com.neulogistics.contrib.procuredcenter.api.service.ThreadLocalService;
import com.neulogistics.contrib.procuredcenter.domain.model.aggregate.Goods;
import com.neulogistics.contrib.procuredcenter.domain.model.aggregate.GoodsSet;
import com.neulogistics.contrib.procuredcenter.domain.model.aggregate.Vendor;
import com.neulogistics.contrib.procuredcenter.domain.repository.IGoodsRepository;
import com.neulogistics.contrib.procuredcenter.domain.repository.IGoodsSetRepository;
import com.neulogistics.contrib.procuredcenter.domain.repository.IVendorRepository;
import com.neulogistics.infrastructure.cache.idservice.RedisIdUtil;
import com.neulogistics.infrastructure.common.annotation.ProduceEvent;
import com.neulogistics.infrastructure.common.serviceresult.BaseResponse;
import com.neulogistics.infrastructure.common.serviceresult.ErrorCode;
import com.neulogistics.infrastructure.common.serviceresult.ResultUtils;
import com.neulogistics.infrastructure.integrationeventlog.model.IntegrationEventConstant;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

@Component
public class CreateGoodsCommandHandler implements IRequestHandler<CreateGoodsCommand, BaseResponse<String>> {
    @Resource
    IGoodsSetRepository goodsSetRepository;

    @Resource
    IVendorRepository vendorRepository;

    @Resource
    IGoodsRepository goodsRepository;

    @Resource
    IProcuredCenterIntegrationEventService procuredCenterIntegrationEventService;

    @Resource
    TransactionTemplate transactionTemplate;

    @Resource
    RedisIdUtil redisIdUtil;

    @Override
    @ProduceEvent
    public BaseResponse<String> handle(CreateGoodsCommand command) throws Exception {
        // 检查二级分类是否存在
        GoodsSet goodsSet = goodsSetRepository.findById(command.setId);
        if(goodsSet == null){
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
        }
        // 检查供应商是否存在
        Vendor vendor = vendorRepository.findById(command.vendorInfo.getVendorId());
        if(vendor == null){
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
        }

        Goods goods = new Goods();
        BeanUtils.copyProperties(command, goods);

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                // 持久化
                goodsRepository.save(goods);

                // 发布新增商品事件，所有库房更新库存目录
                Long eventId = redisIdUtil.nextId(IntegrationEventConstant.Integration_Event_Id_Key);
                GoodsCreatedIntegrationEvent goodsCreatedIntegrationEvent =
                        new GoodsCreatedIntegrationEvent(eventId, goods.getGoodsId(), goods.getGoodsName(), goods.getMeasureUnit());
                Long transactionId = ThreadLocalService.transactionId.get();
                procuredCenterIntegrationEventService.addAndSaveEvent(goodsCreatedIntegrationEvent, transactionId);
            } catch (Exception e){
                // 触发回滚
                throw new RuntimeException(e.getCause().getMessage());
            }
            }
        });

        return ResultUtils.success(goods.getGoodsId().toString());
    }
}
